#if defined(_MSC_VER)
#pragma once
#endif

#ifndef LM_CORE_FILM_H
#define LM_CORE_FILM_H

#include "lm.h"
#include "point.h"
#include "memory.h"
#include "spectrum.h"

class Film : public ReferenceCounted
{
public:
	Film(int xRes, int yRes) : xResolution(xRes), yResolution(yRes) { }
	virtual ~Film();	/* Need to modify */
	virtual void AddSamples(const Point2 &ImageSample, const Spectrum &L) = 0;
	//virtual void Splat(const Point2 &CameraSample, const Spectrum &L) = 0;
	virtual void GetSampleExtent(int *xStart, int *yStart, int *xEnd, int *yEnd) const = 0;
	//virtual void GetPixelExtent(int *xStart, int *yStart, int *xEnd, int *yEnd) const = 0;
	virtual void Display() = 0;
	virtual void UpdateDisplay(int x0, int y0, int x1, int y1) = 0;
	virtual void WriteImage() = 0;
	virtual void Clear() = 0;
	virtual Spectrum Get(int x, int y) const = 0;
	inline Point2 GetSize() const {
		return Point2(xResolution, yResolution);
	}
	inline void GetSize(Point2 *pt) const {
		pt = new Point2(xResolution, yResolution);
	}
	inline void GetSize(int *x, int *y) const {
		*x = xResolution;
		*y = yResolution;
	}
	std::string ToString() const {
		std::ostringstream oss;
		//oss << nReference;
		oss << "Unimplemented ToString functions in class Film";
		Warning("%s\n",oss.str().c_str());
		return oss.str();
	}
	// Public data
	int xResolution, yResolution;
};

// Pixel structure for film
struct Pixel {
	Pixel(): L(0.f) {
		alpha = 0.f;
		weightSum = 0.f;
	}
	void Clear() {
		L.Clear();
		weightSum = 0.f;
		alpha = 0.f;
	}
	std::string ToString() const {
		std::ostringstream oss;
		oss << "Pixel:" << std::endl;
		oss << L <<std::endl;
		oss << "alpha = " << alpha << std::endl;
		oss << "weightSum = " << weightSum;
		return oss.str();
	}
	Spectrum L;
	float alpha, weightSum;
};

// RGB Pixel representation
struct RGBPixel {
	uint8_t r, g, b;
	RGBPixel(uint8_t ir, uint8_t ig, uint8_t ib) {
		Set(ir, ig, ib);
	}
	RGBPixel() : r(0), g(0), b(0) { }
	void Clear() { 
		r = g = b = 0;
	}
	void Set(uint8_t ir, uint8_t ig, uint8_t ib) {
		r = ir;
		g = ig;
		b = ib;
	}
	void Set(const RGBPixel &other) {
		r = other.r;
		g = other.g;
		b = other.b;
	}
	std::string ToString() const {
		std::ostringstream oss;
		oss << "RBG-Pixel:" << std::endl;
		oss << "r = " << r << " g = " << g << " b = " << b;
		return oss.str();
	}
};

#endif	// LM_CORE_FILM_H